#include "../../HObject.h"
#include "../../Domain/HelixMesh.h"
#include "SimpleOpenGLMeshRenderer.h"
#include "OpenGLSupport.h"

namespace helix
{

	void SimpleOpenGLMeshRenderer::renderMesh(Mesh *mesh)
	{

		//this always has to be available
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,0,mesh->getRawVertDataBuffer());         //gets the vertex data

		//chech to see if normal data is available
		//if it is, enable and update the normal data
		bool normals = false;
		if(mesh->isBufferAvailable(Mesh::NORMAL_BUFFER))
		{
			normals = true;
			glEnableClientState(GL_NORMAL_ARRAY);
			glNormalPointer(GL_FLOAT,0,mesh->getRawDataBuffer(Mesh.NORMAL_BUFFER));
		}

		//check to see if vertex color data is available
		//if it is, enable and set the vertex color data
		int colorsPerVert = 0;
		if(mesh->isBufferAvailable(Mesh::RGB_COLOR_BUFFER))
			colorsPerVert = 3;
		else if(mesh->isBufferAvailable(Mesh::RGBA_COLOR_BUFFER))
			colorsPerVert = 4;
		if(colorsPerVert > 0)
		{
			glEnableClientState(GL_COLOR_ARRAY);
			float *data = NULL;
			if(colorsPerVert == 3)
				data = mesh->getRawDataBuffer(Mesh::RGB_COLOR_BUFFER);
			else
				data = mesh->getRawDataBuffer(Mesh::RGBA_COLOR_BUFFER);
			glColorPointer(colorsPerVert,GL_FLOAT,0,data);
		}

		//check to see if texture coordinate data is available
		//if it is, enable and set the vertex color data
		int coordinatesPerVert = 0;
		if(mesh->isBufferAvailable(Mesh::TEX_COORD_1D_BUFFER))
			coordinatesPerVert = 1;
		else if(mesh->isBufferAvailable(Mesh::TEX_COORD_2D_BUFFER))
			coordinatesPerVert = 2;
		else if(mesh->isBufferAvailable(Mesh::TEX_COORD_3D_BUFFER))
			coordinatesPerVert = 3;
		if(coordinatesPerVert > 0)
		{
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			float *data = NULL;
			switch(coordinatesPerVert)
			{
				case 1:	data = mesh->getRawDataBuffer(Mesh::TEX_COORD_1D_BUFFER); break;
				case 2:	data = mesh->getRawDataBuffer(Mesh::TEX_COORD_2D_BUFFER); break;
				case 3:	data = mesh->getRawDataBuffer(Mesh::TEX_COORD_3D_BUFFER); break;
			}
			glTexCoordPointer(coordinatesPerVert,GL_FLOAT,0,data);
		}

		//The actual drawing code.  This renders the mesh and all of its states
		int drawType = 0;
		switch(mesh->getVertsPerFace())
		{
			case Mesh::POINT_MESH:		drawType = GL_POINTS; break;
			case Mesh::LINE_MESH:		drawType = GL_LINES; break;
			case Mesh::TRIANGLE_MESH:	drawType = GL_TRIANGLES; break;
			case Mesh::QUAD_MESH:		drawType = GL_QUADS; break;
		}

		unsigned int *indices = mesh->getRawFaceDataBuffer();
		unsigned int numIndices = (unsigned int)mesh->getNumberOfFaces()*mesh->getVertsPerFace();

		glDrawElements(drawType,				//The type of faces to draw
						numIndices,				//The number of indices to draw
						GL_UNSIGNED_INT,		//The vertex indices are stored as unsigned ints
						indices);				//The array of vertex indices


		//disable all the client states
		glDisableClientState(GL_VERTEX_ARRAY);
		if(normals)
			glDisableClientState(GL_NORMAL_ARRAY);
		if(colorsPerVert > 0)
			glDisableClientState(GL_COLOR_ARRAY);
		if(coordinatesPerVert > 0)
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}

}

